#ifndef DISPLAYWIND_H
#define DISPLAYWIND_H

#include <QWidget>
#include <QMutex>
#include "ijkmediaplayer.h"
#include "imagescaler.h"
#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
//#include <QOpenGLFunctions_4_0_Core>
//#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram)
QT_FORWARD_DECLARE_CLASS(QOpenGLTexture)

namespace Ui {
class DisplayWind;
}

class DisplayWind : public QOpenGLWidget, public  QOpenGLFunctions_3_3_Core
{
    Q_OBJECT

public:
    explicit DisplayWind(QWidget *parent = 0);
    ~DisplayWind();
    int Draw(const Frame *frame);
    void DeInit();
    void StartPlay();
    void StopPlay();

    void initVAO();
    void initShader();
    void initTexture();
    void   allocTexture();
    void renderYUV420P(unsigned char* yuvData, int width, int height);


    // 旋转相关
    enum RO_ANG {
         NORMALL = 0,
         RORATE,
         FLIVP
    };

    void doRotate(enum RO_ANG type);
    void SetWarmColor();
    void SetColdColor();
    void SetNorColor();

    // 检测错误的函数
    GLenum glCkeckError_(const char* file, int line){
        GLenum errorCode;
        while((errorCode = glGetError()) != GL_NO_ERROR)
        {
            std::string error;
            switch (errorCode) {
            case GL_INVALID_ENUM:   error = "INVALID_ENUM"; break;
            case GL_INVALID_VALUE:  error = "INVALID_VALUE"; break;
            case GL_INVALID_OPERATION: error = "INVALID_OPERATION"; break;
            case GL_STACK_OVERFLOW: error = "STACK_OVERFLOW"; break;
            case GL_STACK_UNDERFLOW: error = "STACK_UNDERFLOW"; break;
            case GL_OUT_OF_MEMORY: error = "OUT_OF_MEMORY"; break;
            case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break;
            }
            std::cout << error << " | " << file << " (" << line << ")" << std::endl;
        }
        return errorCode;
    }
    #define glCheckError() glCheckError_(__FILE__, __LINE__)

    QOpenGLContext m_context; // 主要的OpenGL上下文
    QOpenGLContext m_sharedContext; // 共享的OpenGL上下文
protected:
    // OpenGL
    virtual void initializeGL() override;
    virtual void resizeGL(int w, int h) override;
    virtual void paintGL() override;
    // 这里不要重载event事件，会导致paintEvent不被触发
    //void paintEvent(QPaintEvent *) override;
   //void resizeEvent(QResizeEvent *event) override;


private:
    Ui::DisplayWind *ui;

    int m_nLastFrameWidth; ///< 记录视频宽高
    int m_nLastFrameHeight;
    bool is_display_size_change_ = false;

    int x_ = 0; //  起始位置
    int y_ = 0;
    int video_width = 0;
    int video_height = 0;
    int img_width = 0;
    int img_height = 0;
    int win_width_ = 0;
    int win_height_ = 0;
    bool req_resize_ = false;
    QImage img;
    VideoFrame dst_video_frame_;
    QMutex m_mutex;
    ImageScaler *img_scaler_ = NULL;

    int play_state_ = 0;    // 0 初始化状态; 1 播放状态; 2 停止状态


    // opengl 相关
    QOpenGLShaderProgram *m_shader_program;  //
    unsigned int m_texture = 0;
    GLuint g_Texture2D[3]; // 纹理ID
    GLuint nTextureUniform[3];//纹理位置ID
    // 旋转
    glm::mat4 trans;
    int transAngle = 0;



    QOpenGLBuffer vbo;
    GLuint textureUniformY,textureUniformU,textureUniformV; 	//opengl中y、u、v分量位置
    QOpenGLTexture *textureY = nullptr,*textureU = nullptr,*textureV = nullptr;
    GLuint idY,idU,idV ,in_color_id; 			//自己创建的纹理对象ID，创建错误返回0
    uint videoW,videoH;
    uchar *yuvPtr = nullptr;

    FILE* dump_yuv;

    GLuint VAO = 0,VBO=0,EBO=0;
    GLuint g_shaderprogram=0;


};

#endif // DISPLAYWIND_H
